'use strict';

const Controller = require('../lib/controller');

class UserController extends Controller {
  async index() {

    if (this.ctx.request.query.id) {
      switch (String(this.ctx.request.query.act)) {
        case 'edit':
          await this.editUserInfo(false);
          break;
        case 'update':
          await this.editUserInfo(true);
          break;
        case 'delete':
          await this.deleteUser();
          break;
        default:
          await this.viewUserInfo();
      }
    } else {
      await this.viewUserList();
    }
  }

  // View User List //////////////////////////////////////////////////////////////
  async viewUserList() {
    // Check current page number
    if (this.ctx.request.query.page) {
      this.ctx.request.query.page = this.ctx.helper.checkInt(this.ctx.request.query.page);
      if (this.ctx.request.query.page <= 0) {
        this.ctx.request.query.page = 1;
      }
    } else {
      this.ctx.request.query.page = 1;
    }

    let users,
      entryCount;

    const sqlWHERE = '';
    const strSQL = 'SELECT user_id, user_name, user_email, user_hideEmail, user_homepage, user_articleCount, user_commentCount, user_lastVisit FROM blog_user ' + sqlWHERE + ' ORDER BY user_articleCount DESC, user_commentCount DESC, user_lastVisit DESC';

    users = await this.ctx.app.connBlog.query(strSQL, this.ctx.app.theCache.settings.articlePerPageList, this.ctx.request.query.page, false);

    if (users) {
      entryCount = this.ctx.app.connBlog.recordCount;
    } else {
      users = '';
      entryCount = 0;
    }
    const data = {
      strTitle: this.ctx.__('reg_users'),
      arrUser: users,
      intEntryCount: entryCount,
      intEntryPerPage: this.ctx.app.theCache.settings.articlePerPageList,
      intCurrentPage: this.ctx.request.query.page,
    };
    await this.ctx.render('user/userList.ejs', data);
  }

  // View User Info /////////////////////////////////////////////////////////////
  async viewUserInfo() {
    const tUser = this.ctx.service.user;
    const strError = await tUser.loadByID(this.ctx.request.query.id);

    if (strError != false) {
      return await this.ctx.response.redirectMessage(
        this.ctx.__('error'),
        strError,
        this.ctx.__('goback'),
        'javascript:window.history.back();',
        false,
        'errorbox'
      );
    }

    const data = {
      strTitle: this.ctx.__('user_info'),
      tUser,
    };
    await this.ctx.render('user/userInfo.ejs', data);
  }

  // Edit User Info /////////////////////////////////////////////////////////////
  async editUserInfo(bSave) {
    const tUser = this.ctx.service.user;
    let strError = await tUser.loadByID(this.ctx.request.query.id);

    if (strError != false) {
      return await this.ctx.response.redirectMessage(
        this.ctx.__('error'),
        strError,
        this.ctx.__('goback'),
        'javascript:window.history.back();',
        false,
        'errorbox'
      );
    }

    if (tUser.id != this.ctx.theUser.id && this.ctx.theUser.groupID != 1) {
      return await this.ctx.response.redirectMessage(
        this.ctx.__('error'),
        this.ctx.__('no_rights'),
        this.ctx.__('goback'),
        'javascript:window.history.back();',
        false,
        'errorbox'
      );
    }

    if (!bSave) {
      // Output edit form
      this.ctx.genSecurityCode();

      const data = {
        strTitle: this.ctx.__('edit_profile'),
        tUser,
      };
      return await this.ctx.render('user/userForm.ejs', data);
    }

    // Save edit result
    strError = '';

    // Let Admin change User's Group
    if (this.ctx.theUser.groupID == 1) {
      this.ctx.request.body.groupid = this.ctx.helper.checkInt(this.ctx.request.body.groupid);
      for (let i = 0; i < this.ctx.app.theCache.userGroup.length; i++) {
        if (this.ctx.request.body.groupid == this.ctx.app.theCache.userGroup[i].id) {
          tUser.groupID = this.ctx.request.body.groupid;
          break;
        }
      }
    }

    // Check Current Password
    if (!this.ctx.helper.checkPassword(this.ctx.request.body.oldpassword)) {
      strError += '<li>' + this.ctx.__('old_password_invalid') + '</li>';
    } else {
      if (this.ctx.theUser.groupID == 1 && this.ctx.theUser.id != tUser.id) {
        const tmpA = await this.ctx.app.connBlog.query('SELECT user_password, user_salt FROM blog_user WHERE user_id=' + this.ctx.theUser.id, 1, 1);
        if (!tmpA || !tmpA.length) {
          strError += '<li>' + this.ctx.__('user_not_found') + '</li>';
        } else {
          if (tmpA[0].user_password != this.ctx.helper.SHA1(this.ctx.request.body.oldpassword + tmpA[0].user_salt)) {
            strError += '<li>' + this.ctx.__('old_password_invalid') + '</li>';
          }
        }
      } else {
        if (tUser.password != this.ctx.helper.SHA1(this.ctx.request.query.oldpassword + tUser.salt)) {
          strError += '<li>' + this.ctx.__('old_password_invalid') + '</li>';
        }
      }
    }

    // Check Post data
    if (strError == '') strError += await tUser.fillFromPost(true, true, this.ctx.theUser.groupID == 1);

    // Check for post data
    if (strError != '') {
      // Avoid password breaker
      if (this.ctx.session.loginfail > 3) {
        this.ctx.session.lbsSecurityCode = null;
      }
      if (!this.ctx.session.loginfail) {
        this.ctx.session.loginfail = 0;
      }
      this.ctx.session.loginfail++;

      // Return with error message
      return await this.ctx.response.redirectMessage(
        this.ctx.__('error'),
        strError,
        this.ctx.__('goback'),
        'javascript:window.history.back();',
        false,
        'errorbox'
      );
    }

    // Clean up to avoid abuse
    this.ctx.session.lbsSecurityCode = undefined;

    await tUser.update();

    await this.ctx.response.redirectMessage(
      this.ctx.__('done'),
      this.ctx.__('profile_updated'),
      this.ctx.__('redirect'),
      '?id=' + tUser.id,
      true,
      'messagebox'
    );

  }

  // Delete User /////////////////////////////////////////////////////////////
  async deleteUser() {
    const tUser = this.ctx.service.user;
    const strError = await tUser.loadByID(this.ctx.request.query.id);

    if (strError != false) {
      return await this.ctx.response.redirectMessage(
        this.ctx.__('error'),
        strError,
        this.ctx.__('goback'),
        'javascript:window.history.back();',
        false,
        'errorbox'
      );
    }

    if (tUser.id != theUser.id && theUser.groupID != 1) {
      return await this.ctx.response.redirectMessage(
        this.ctx.__('error'),
        this.ctx.__('no_rights'),
        this.ctx.__('goback'),
        'javascript:window.history.back();',
        false,
        'errorbox'
      );
    }
    await tUser.doDelete();

    await this.ctx.response.redirectMessage(
      this.ctx.__('done'),
      this.ctx.__('user_deleted'),
      this.ctx.__('redirect'),
      '?',
      true,
      'messagebox'
    );


  }

  /**
   * 登陆表单页
   * @route login.asp
   */
  async login() {

    // Generate security code
    this.ctx.genSecurityCode();

    const data = { strTitle: this.ctx.__('login') };

    await this.ctx.render('login.ejs', data);
  }

  /**
   *
   * @route login.asp?act=login
   * @method POST
   */
  async doLogin() {
    if (this.ctx.theUser.loggedIn) {
      // If user is already logged in
      return await this.ctx.response.redirectMessage(
        this.ctx.__('error'),
        this.ctx.__('login_already'),
        this.ctx.__('goback'),
        'default.asp',
        false,
        'errorbox'
      );
    }

    let strError = await this.ctx.theUser.login(
      this.ctx.request.body.username,
      this.ctx.request.body.password,
      this.ctx.request.body.cookiesday,
      true,
      this.ctx.request.body.scode
    );
    if (strError == false) {
      await this.ctx.response.redirectMessage(
        this.ctx.__('done'),
        this.ctx.__('login_done'),
        this.ctx.__('redirect'),
        this.ctx.request.originalUrl,
        true,
        'messagebox'
      );
    } else {
      strError = this.ctx.__('login_error') + '<ul id="errorlist">' + strError +
        '</ul>';
      return await this.ctx.response.redirectMessage(
        this.ctx.__('error'),
        strError,
        this.ctx.__('goback'),
        'javascript:window.history.back();',
        false,
        'errorbox'
      );
    }
    await this.ctx.genSecurityCode();

  }

  /**
   *
   * @route login.asp?act=logout
   */
  async logout() {
    if (this.ctx.service.user.loggedIn) {
      await this.ctx.service.user.logout(true);
    } else {
      await this.ctx.service.user.logout(false);
    }

    this.ctx.service.cache.genSecurityCode();

    this.ctx.locals.strTitle = this.ctx.__('logout');

    this.ctx.response.redirectMessage(
      this.ctx.__('done'),
      this.ctx.__('logout_done'),
      this.ctx.__('redirect'),
      this.ctx.request.originalUrl,
      true,
      'messagebox'
    );
  }

  async register() {
    this.ctx.locals.strTitle = this.ctx.__('reg_title');

    if (this.ctx.app.theCache.settings.enableRegister != 1) {
      // If register is disabled
      await this.ctx.response.redirectMessage(
        this.ctx.__('error'),
        this.ctx.__('reg_disabled'),
        this.ctx.__('goback'),
        'default.asp',
        false,
        'errorbox'
      );
      return;
    }

    if (this.ctx.session.registered || this.ctx.theUser.loggedIn) {
      // If user is already logged in
      await this.ctx.response.redirectMessage(
        this.ctx.__('error'),
        this.ctx.__('reg_already'),
        this.ctx.__('goback'),
        'default.asp',
        false,
        'errorbox'
      );
      return;
    }

    switch (String(this.ctx.request.query.act)) {
      case 'agree':
        // Make sure user is post from the form
        this.ctx.genSecurityCode();

        await this.ctx.render('user/registerForm.ejs', {});

        break;
      case 'save':
        // Do register
        let strError = await this.ctx.theUser.register(true);

        if (strError != false) {
          // Show errors
          strError = this.ctx.__('reg_error') + '<ul id="errorlist">' + strError + '</ul>';
          await this.ctx.response.redirectMessage(
            this.ctx.__('error'),
            strError,
            this.ctx.__('goback'),
            'javascript:window.history.back();',
            false,
            'errorbox'
          );
        } else {
          // Redirect to index
          await this.ctx.response.redirectMessage(
            this.ctx.__('done'),
            this.ctx.__('reg_done'),
            this.ctx.__('redirect'),
            'default.asp',
            true,
            'messagebox'
          );
        }
        break;
      default:
        await this.ctx.render('user/registerAgreement.ejs', {});
    }

  }

}

module.exports = UserController;
